package com.muqi.server.common.utilis;

import com.muqi.server.domain.bo.CollaborativeFilteringBO;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealMatrix;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class StudentSimilarityRecommender {


    public List<CollaborativeFilteringBO> recommendForSpecifiedStudents(List<CollaborativeFilteringBO> targetStudents, List<CollaborativeFilteringBO> allStudents, int topN) {
        Map<CollaborativeFilteringBO, Double> similarityScores = new HashMap<>();

        for (CollaborativeFilteringBO targetStudent : targetStudents) {
            for (CollaborativeFilteringBO student : allStudents) {
                if (!student.getName().equals(targetStudent.getName())) { // 排除自己
                    similarityScores.merge(student, calculateCosineSimilarity(targetStudent, student), Double::sum);
                }
            }
        }

        return similarityScores.entrySet().stream()
                .sorted(Map.Entry.<CollaborativeFilteringBO, Double>comparingByValue().reversed())
                .limit(topN)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }


    public RealMatrix calculateStudentSimilarity(List<CollaborativeFilteringBO> students) {
        int studentCount = students.size();
        RealMatrix similarityMatrix = MatrixUtils.createRealMatrix(studentCount, studentCount);

        for (int i = 0; i < studentCount; i++) {
            for (int j = 0; j < studentCount; j++) {
                if (i != j) {
                    similarityMatrix.setEntry(i, j, calculateCosineSimilarity(students.get(i), students.get(j)));
                } else {
                    similarityMatrix.setEntry(i, j, 1.0); // 自己和自己的相似度设为1
                }
            }
        }

        return similarityMatrix;
    }

    // 计算两个学生之间的余弦相似度
    private double calculateCosineSimilarity(CollaborativeFilteringBO studentA, CollaborativeFilteringBO studentB) {
        double gpaA = Double.parseDouble(studentA.getGpa());
        double gpaB = Double.parseDouble(studentB.getGpa());
        double semesterA = studentA.getSemester();
        double semesterB = studentB.getSemester();

        double dotProduct = gpaA * gpaB + semesterA * semesterB;
        double normA = Math.sqrt(gpaA * gpaA + semesterA * semesterA);
        double normB = Math.sqrt(gpaB * gpaB + semesterB * semesterB);

        return dotProduct / (normA * normB);
    }

    // 根据相似度矩阵生成推荐
    public void recommendSimilarStudents(List<CollaborativeFilteringBO> students, RealMatrix similarityMatrix, int topN) {
        int studentCount = students.size();

        for (int i = 0; i < studentCount; i++) {
            Map<Integer, Double> similarityScores = new HashMap<>();

            for (int j = 0; j < studentCount; j++) {
                if (i != j) {
                    similarityScores.put(j, similarityMatrix.getEntry(i, j));
                }
            }

            List<String> recommendations = similarityScores.entrySet().stream()
                    .sorted(Map.Entry.<Integer, Double>comparingByValue().reversed())
                    .limit(topN)
                    .map(entry -> students.get(entry.getKey()).getName())
                    .collect(Collectors.toList());

            students.get(i).setRecommendation(recommendations);
        }




    }
}
